package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"sync"
	"time"
)

// ServerConfig 定义配置文件解析后的结构
type ServerConfig struct {
	TermServerIP    string
	TermServerPort  int
	BoxieServerIP   string
	BoxieServerPort int
	MonitorPort     int
}

// TCPClientModel 定义tcp的结构体
type TCPClientModel struct {
	// 终端的连接
	TConn net.Conn
	// 服务端的连接
	SConn net.Conn
	//发送chan term->boxie
	SendChan chan []byte
	//发送chan   boxie->term
	SendChanB chan []byte
	//心跳chan
	ClientPingChan chan int
	//b停止chan
	StopChan chan int
	//T停止chan
	StopChanT chan int
	BusCode   string
}

var conf ServerConfig
var terminalslMap sync.Map /*创建在线车辆集合 */

// clientHandle单独处理客户端的请求
func (tcpClient *TCPClientModel) clientHandle() {
	tcpClient.TConn.SetReadDeadline(time.Now().Add(time.Minute * 3))
	defer func() {
		tcpClient.TConn.Close()
		tcpClient.StopChan <- 1
	}()

	for {
		select {
		case <-tcpClient.StopChanT:
			goto stop
		default:
			data := make([]byte, 1024)
			//从conn中读取数据
			n, err := tcpClient.TConn.Read(data)
			//fmt.Fprintf(os.Stderr, "term Read res:%d", n)

			//如果读取数据大小为0或出错则退出
			if n == 0 || err != nil {
				fmt.Fprintf(os.Stderr, "Read error")
				goto stop
			}
			s := data[:n]
			// // 发送数据
			// tcpClient.SendChan <- s
			buscode := string(s[12:20])
			//	fmt.Println("buscode:" + buscode)
			tcpClient.BusCode = buscode
			//terminalslMap[buscode] = time.Now().Format("2006-01-02 15:04:05")
			terminalslMap.Store(buscode, time.Now().Format("2006-01-02 15:04:05"))
			tcpClient.SConn.Write(data)
		}
	}

stop:
	//log.Println("关闭连接")
	terminalslMap.Delete(tcpClient.BusCode)
	//delete(terminalslMap, tcpClient.BusCode)
}

// ServerHandle 单独处理客户端的请求
func (tcpClient *TCPClientModel) ServerHandle() {
	tcpClient.SConn.SetReadDeadline(time.Now().Add(time.Minute * 3))
	defer func() {
		tcpClient.SConn.Close()
		tcpClient.StopChanT <- 1
	}()

	for {
		select {
		case <-tcpClient.StopChan:
			goto stop
		default:
			data := make([]byte, 1024)
			//从conn中读取数据
			n, err := tcpClient.SConn.Read(data)
			//fmt.Fprintf(os.Stderr, "boxie Read res:%d", n)

			//如果读取数据大小为0或出错则退出
			if n == 0 || err != nil {
				fmt.Fprintf(os.Stderr, "boxie Read error")
				goto stop
			}
			tcpClient.TConn.Write(data)
			// s := data[:n]
			// // 发送数据
			// tcpClient.SendChanB <- s
		}
	}

stop:
	//log.Println("关闭连接")
	terminalslMap.Delete(tcpClient.BusCode)

}

// logicHandle 单独处理客户端的请求
func (tcpClient *TCPClientModel) logicHandle() {
	for {
		select {
		//数据发送统一接口
		case data, _ := <-tcpClient.SendChan:
			//fmt.Fprintf(os.Stdout, "term->boxie:"+hex.EncodeToString(data))
			tcpClient.SConn.Write(data)
		case data, _ := <-tcpClient.SendChanB:
			//fmt.Fprintf(os.Stdout, "boxie->term:"+hex.EncodeToString(data))
			tcpClient.TConn.Write(data)
		case <-tcpClient.StopChan:
			goto stop
		}
	}
stop:
	//log.Println("关闭连接")
}

func main() {
	//terminalslMap = make(map[string]string)
	JSONParse := NewJSONStruct()
	conf = ServerConfig{}
	//下面使用的是相对路径，config.json文件和main.go文件处于同一目录下
	JSONParse.Load(GetExePath()+"/config", &conf)
	fmt.Println("monitorport:" + fmt.Sprintf("%d", conf.MonitorPort) + ",BoxieServerIP:" + conf.BoxieServerIP + ",BoxieServerPort:" + fmt.Sprintf("%d", conf.BoxieServerPort))

	service := ":142"
	tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
	checkError(err)
	listener, err := net.ListenTCP("tcp", tcpAddr)
	checkError(err)
	go monitorInput()

	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Fprintf(os.Stderr, "accept error: %s", err.Error())
			continue
		}
		//fmt.Fprintf(os.Stderr, "connect come")
		//	通过goroutine来处理用户的请求
		sConn, err := net.Dial("tcp", conf.BoxieServerIP+":"+fmt.Sprintf("%d", conf.BoxieServerPort))
		if err != nil {
			log.Println(err)
			return
		}
		tcpClientM := &TCPClientModel{
			TConn:     conn,
			SConn:     sConn,
			StopChan:  make(chan int, 1),
			StopChanT: make(chan int, 1),
			SendChan:  make(chan []byte, 1024),
			SendChanB: make(chan []byte, 1024),
		}
		// go tcpClientM.logicHandle()
		go tcpClientM.clientHandle()
		go tcpClientM.ServerHandle()
	}

}

func monitorInput() {
	f := bufio.NewReader(os.Stdin) //读取输入的内容
	var String string
	var Number int
	for {
		fmt.Print("请输入一些字符串>")
		Input, _ := f.ReadString('\n') //定义一行输入的内容分隔符。
		if len(Input) == 1 {
			continue //如果用户输入的是一个空行就让用户继续输入。
		}
		fmt.Printf("您输入的是:%s", Input)
		fmt.Sscan(Input, &String, &Number) //将Input
		if String == "stop" {
			break
		}

		terminalslMap.Range(func(k, v interface{}) bool {
			fmt.Println("lasttime:", k, v)
			return true
		})
		// for country := range terminalslMap {
		// 	fmt.Println(country, "lasttime:", terminalslMap.Load(country)
		// }
	}
}
func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "server Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

// JSONStruct 结构体
type JSONStruct struct {
}

// NewJSONStruct 读取配置文件
func NewJSONStruct() *JSONStruct {
	return &JSONStruct{}
}

// Load 读取配置文件
func (jst *JSONStruct) Load(filename string, v interface{}) {
	//ReadFile函数会读取文件的全部内容，并将结果以[]byte类型返回
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return
	}

	//读取的数据为json格式，需要进行解码
	err = json.Unmarshal(data, v)
	if err != nil {
		return
	}
}

// GetExePath 获取exe路径
func GetExePath() string {
	pwd, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	fmt.Println(pwd)
	return pwd
}

// WriteWithIo 使用io.WriteString()函数进行数据的写入
func WriteWithIo(name, content string) {
	fileObj, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println("Failed to open the file", err.Error())
		os.Exit(2)
	}
	if _, err := io.WriteString(fileObj, content); err == nil {
		fmt.Println("Successful appending to the file with os.OpenFile and io.WriteString.", content)
	}
}
